#![no_std]
#![no_main]
extern crate alloc;

use alloc::boxed::Box;
use alloc::rc::Rc;
use core::cell::RefCell;
use core::fmt::Debug;
use display_interface_spi::SPIInterfaceNoCS;
use embedded_graphics::mono_font::iso_8859_7::FONT_5X8;
use embedded_graphics::mono_font::MonoTextStyle;
use embedded_graphics::text::Text;
use embedded_graphics_core::Drawable;
use embedded_graphics_core::pixelcolor::BinaryColor;
use embedded_graphics_core::prelude::{DrawTarget, Point};
use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayMs;
use esp_hal::clock::{CpuClock, RadioClockController};
use esp_hal::delay::Delay;
use esp_hal::{main, spi, Blocking};
use esp_hal::gpio::{Level, Output, OutputConfig};
use esp_hal::i2c::master::I2c;
use esp_hal::peripherals::Peripherals;
use esp_hal::rtc_cntl::Rtc;
use esp_hal::spi::master::Config;
use esp_hal::spi::master::Spi;
use esp_hal::time::{Duration, Instant, Rate};
use esp_hal::timer::systimer::SystemTimer;
use esp_hal::timer::timg::TimerGroup;
use esp_println::logger::{init_logger, init_logger_from_env};
use log::{error, info, warn, LevelFilter};
use mipidsi::Display;
use slint::platform::{Platform, WindowAdapter};
use slint::platform::software_renderer::{LineBufferProvider, Rgb565Pixel};
use slint::{PhysicalSize, PlatformError};
use ssd1306::{I2CDisplayInterface, Ssd1306};
use ssd1306::mode::BufferedGraphicsMode;
use ssd1306::prelude::*;

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
    loop {
        error!("panic:{}",info);
    }
}


slint::slint!(
export component MainView {
    width: 128px;
    height: 64px;
    Rectangle {
        x:0px;
        y:0px;
        width: 100%;
        height: 100%;
        background: transparent;
        border-color: blue;
        border-width: 5px;
    }

    Rectangle {
        x:10px;
        y:6px;
        width: 50px;
        height: 50px;
        background: blue;
        border-radius: 360px;

    }


}
);



// static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();

#[main]
fn main() -> ! {
    // generator version: 0.3.1
    // init_logger_from_env();
    init_logger(LevelFilter::Debug);
    esp_alloc::heap_allocator!(size: 100 * 1024);

    info!("分配内存完成");
    // 创建平台实例
    let platform = EspPlatform::new();
    slint::platform::set_platform(Box::new(platform)).unwrap();

    info!("开始渲染屏幕了");
    let ui = MainView::new().unwrap();
    //关键设置：禁用自动缩放
    // ui.window().set_scale_factor(1.0);
    ui.window().set_size(PhysicalSize::new(128,64));
    ui.run().unwrap();
    loop{}
    // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-beta.0/examples/src/bin
}

// 平台实现结构体
type SSD = Ssd1306<I2CInterface<I2c<'static,Blocking>>,DisplaySize128x64,BufferedGraphicsMode<DisplaySize128x64>>;
struct EspPlatform{
    window: RefCell<Option<Rc<slint::platform::software_renderer::MinimalSoftwareWindow>>>,
}

impl EspPlatform {
    fn new() -> Self {
        Self {
            window: RefCell::new(None),
        }
    }
}


/// 实现 Platform trait
impl Platform for EspPlatform {
    fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
        let window = slint::platform::software_renderer::MinimalSoftwareWindow::new(
            slint::platform::software_renderer::RepaintBufferType::ReusedBuffer,
        );
        *self.window.borrow_mut() = Some(window.clone());
        info!("成功创建了window");
        Ok(window)
    }

    fn run_event_loop(&self) -> Result<(), PlatformError> {
        let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());

        let peripherals =esp_hal::init(config);

        let i2c = esp_hal::i2c::master::I2c::new(peripherals.I2C0, esp_hal::i2c::master::Config::default()
            .with_frequency(Rate::from_khz(400)))
            .unwrap()
            .with_sda(peripherals.GPIO8)
            .with_scl(peripherals.GPIO9);

        let mut display = Ssd1306::new(
            I2CDisplayInterface::new(i2c),
            DisplaySize128x64,
            DisplayRotation::Rotate0).into_buffered_graphics_mode();

        let window = self.window.borrow().clone().unwrap();

        info!("进入了loop run");
        // 初始化显示
        display.set_rotation(DisplayRotation::Rotate0).unwrap();
        display.init().unwrap();
        display.clear(BinaryColor::On).unwrap();
        display.flush().unwrap();
        info!("清理屏幕 on");

        let delay = Delay::new();
        delay.delay(Duration::from_secs(1));
        display.clear(BinaryColor::Off).unwrap();
        display.flush().unwrap();
        info!("清理屏幕 off");
        window.set_size(PhysicalSize::new(128,64));


        // 创建行缓冲区
        // let mut line_buffer = SlintOledBuffer { display: &mut display };

        // 假设 display_width 是显示器的宽度，the_frame_buffer 是帧缓冲区
        let display_width = 128; // 根据实际显示宽度设置
        let mut the_frame_buffer = [Rgb565Pixel(0); 128 * 64]; // 假设显示分辨率为128x64

        loop {
            // 更新UI状态
            slint::platform::update_timers_and_animations();
            /*info!("Window size: {:?}", window.size());
            info!("Has active animations: {}", window.has_active_animations());*/
            // 渲染UI
            window.draw_if_needed(|renderer| {
                info!("进入渲染回调");
                // renderer.render_by_line(line_buffer);
                renderer.render_by_line(FrameBuffer{ frame_buffer: &mut the_frame_buffer, stride: display_width,display:&mut display });
                // info!("buf len {}",the_frame_buffer.len());
                info!("退出渲染回调");
                display.flush().unwrap();
            });
            // delay.delay(Duration::from_secs(2));
            // window.request_redraw();
        }
    }

    fn duration_since_start(&self) -> core::time::Duration {
        // 使用定时器获取时间（需要实际硬件计时器实现）
        let time = Instant::now().duration_since_epoch().as_millis();
        // info!("time :{}",time);
        core::time::Duration::from_millis(
            time
        )
        // core::time::Duration::from_millis(unsafe { core::ptr::read_volatile(0x6000_0000 as *const u64) })
    }
}


struct FrameBuffer<'a>{ frame_buffer: &'a mut [Rgb565Pixel], stride: usize,display:&'a mut SSD }
impl<'a> LineBufferProvider for FrameBuffer<'a> {
    type TargetPixel = Rgb565Pixel;
    fn process_line(
        &mut self,
        line: usize,
        range: core::ops::Range<usize>,
        render_fn: impl FnOnce(&mut [Self::TargetPixel]),
    ) {
        let line_start = line * self.stride;
        let line_pixels = &mut self.frame_buffer[line_start..line_start + 128];
        // let line_pixels = &mut self.frame_buffer[line_start..line_start + 128];

        /*info!("要绘制的行为：{} 绘制的range为：{:?}",line,range);
        info!("绘图函数之前的数据：{:?}",line_pixels);*/
        render_fn(&mut line_pixels[range.clone()]);
        /*info!("绘图函数之后的数据：{:?}",line_pixels);*/

        /*let mut oled_line = [0u8; 16];
        for (i, pixel) in line_pixels.iter().enumerate() {
            // 处理所有像素（忽略range）
            let r = (pixel.0 >> 11) & 0x1F;
            if r > 0x10 {
                let byte_idx = i / 8;
                let bit_idx = 7 - (i % 8); //列优先排列
                oled_line[byte_idx] |= 1 << bit_idx;
            }
        }*/

       /* Rgb565Pixel(65503);
        let t = Rgb565Pixel(31);
        let mut oled_line = [0;128];
        for x in line_pixels {
            if &t == x{

            }
        }*/

        let t = Rgb565Pixel(31);
        for (x,row) in line_pixels.iter().enumerate(){
            if row == &t{
                self.display.set_pixel(x as u32, line as u32, true);
            }
        }
        /*let mut oled_line;
        let dark_line= [0x00;128];
        let bright_line = [0xFF;128];
        if line%4 == 0{
            oled_line = dark_line;
            for x in 0..128{
                self.display.set_pixel(x, line as u32, true);
            }
        }else {
            oled_line = bright_line;
        }*/


        // self.display.flush().unwrap();

        // 写入显示
        /*warn!("oled_line :{:?}",oled_line);*/

        // self.display.set_row(line as u8).unwrap();

        // self.display.set_row(line as u8).unwrap();
        // self.display.set_column(0).unwrap();
        // self.display.draw(&oled_line).unwrap();

        // self.display.set_column(0).unwrap();
        // let text = Text::new("hello oled", Point::new(10, 10), MonoTextStyle::new(&FONT_5X8, BinaryColor::On));
        // text.draw(self.display).unwrap();
        // self.display.flush().unwrap();
    }
}


/// 实现 LineBufferProvider
struct SlintOledBuffer {
    display: SSD,
}

impl LineBufferProvider for SlintOledBuffer{
    type TargetPixel = slint::platform::software_renderer::Rgb565Pixel;

    fn process_line(
        &mut self,
        line: usize,
        range: core::ops::Range<usize>,
        render_fn: impl FnOnce(&mut [Self::TargetPixel]),
    ) {
        // 将Slint的RGB565转换为单色像素
        let mut slint_buffer = [slint::platform::software_renderer::Rgb565Pixel(0); 128];
        render_fn(&mut slint_buffer);

        // 转换到OLED需要的二进制格式
        let mut oled_line = [0u8; 16]; // 128 pixels / 8 bits = 16 bytes
        for (i, pixel) in slint_buffer.iter().enumerate() {
            let brightness = (pixel.0 as u32) >> 11; // 取高5位红色分量
            if brightness > 15 { // 阈值判断
                oled_line[i / 8] |= 1 << (i % 8);
            }
        }

        // 写入OLED显示
        self.display.set_row(line as u8).unwrap();
        self.display.set_column(0).unwrap();
        // self.display.data(&oled_line).unwrap();
        // self.display.draw(&embedded_graphics::primitives::Line::new(
        //     embedded_graphics::prelude::Point::new(0, line as i32),
        //     embedded_graphics::prelude::Point::new(127, line as i32),
        // )).unwrap();
        self.display.flush().unwrap();
    }
}
